package com.aliyun.commons.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.serializer.GenericToStringSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.scripting.support.ResourceScriptSource;

/**
 * Redis 配置
 *
 * 
 * @date 2024/11/26
 */
@Configuration
public class RedisConfig {

    @Bean(name = "objectRedisTemplate")
    @Primary
    public RedisTemplate<String, Object> objectRedisTemplate(RedisConnectionFactory connectionFactory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(connectionFactory);

        FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);

        // Use StringRedisSerializer for the key
        template.setKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(fastJsonRedisSerializer);

        // Optionally set hash key/value serializer
        template.setHashKeySerializer(new StringRedisSerializer());
        template.setHashValueSerializer(fastJsonRedisSerializer);

        template.afterPropertiesSet();
        return template;
    }

    @Bean(name = "counterRedisTemplate")
    public RedisTemplate<String, Integer> counterRedisTemplate(RedisConnectionFactory connectionFactory) {
        RedisTemplate<String, Integer> template = new RedisTemplate<>();
        template.setConnectionFactory(connectionFactory);

        // Key 序列化使用 StringRedisSerializer
        template.setKeySerializer(new StringRedisSerializer());
        // Value 序列化使用 GenericToStringSerializer
        template.setValueSerializer(new GenericToStringSerializer<>(Integer.class));

        template.afterPropertiesSet();
        return template;
    }

    @Bean(name = "scriptRedisTemplate")
    public RedisTemplate<String, Object> scriptRedisTemplate(RedisConnectionFactory connectionFactory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(connectionFactory);

        // Set serializers for keys and values
        StringRedisSerializer stringSerializer = new StringRedisSerializer();
        GenericToStringSerializer<Long> longSerializer = new GenericToStringSerializer<>(Long.class);

        template.setKeySerializer(stringSerializer);
        template.setValueSerializer(longSerializer);

        // Initialize RedisTemplate
        template.afterPropertiesSet();

        return template;
    }

    @Bean
    public DefaultRedisScript<Long> delIfPresent() {
        DefaultRedisScript<Long> script = new DefaultRedisScript<>();
        script.setScriptSource(new ResourceScriptSource(new ClassPathResource("/lua/delIfPresent.lua")));
        script.setResultType(Long.class);
        return script;
    }

    @Bean
    public DefaultRedisScript<Long> setExIfAbsent() {
        DefaultRedisScript<Long> script = new DefaultRedisScript<>();
        script.setScriptSource(new ResourceScriptSource(new ClassPathResource("/lua/setExIfAbsent.lua")));
        script.setResultType(Long.class);
        return script;
    }

    @Bean
    public DefaultRedisScript<Long> setExIfPresent() {
        DefaultRedisScript<Long> script = new DefaultRedisScript<>();
        script.setScriptSource(new ResourceScriptSource(new ClassPathResource("/lua/setExIfPresent.lua")));
        script.setResultType(Long.class);
        return script;
    }
}